home *** CD-ROM | disk | FTP | other *** search
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
- <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
- <!-- $Revision: 1.1.2.7 $ -->
-
- <!--
- Copyright 2003-2004 The Apache Software Foundation
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
- <manualpage metafile="custom_errordocs.xml.meta">
- <parentdocument href="./">Miscellaneous Documentation</parentdocument>
-
- <title>International Customized Server Error Messages</title>
-
- <summary>
-
- <note type="warning"><title>Warning:</title>
- <p>This document has not been fully updated
- to take into account changes made in the 2.0 version of the
- Apache HTTP Server. Some of the information may still be
- relevant, but please use it with care.</p>
- </note>
-
- <p>This document describes an easy way to provide your Apache
- HTTP Server with a set of customized error messages which take
- advantage of <a href="../content-negotiation.html">Content
- Negotiation</a> and <module>mod_include</module> to return
- error messages generated by the server in the client's native
- language.</p>
-
- </summary>
-
- <section id="intro">
-
- <title>Introduction</title>
-
- <p>By using SSI, all <directive
- module="core">ErrorDocument</directive> messages
- can share a homogenous and consistent style and layout, and
- maintenance work (changing images, changing links) is kept to a
- minimum because all layout information can be kept in a single
- file.</p>
-
- <p>Error documents can be shared across different servers, or
- even hosts, because all varying information is inserted at the
- time the error document is returned on behalf of a failed
- request.</p>
-
- <p>Content Negotiation then selects the appropriate language
- version of a particular error message text, honoring the
- language preferences passed in the client's request. (Users
- usually select their favorite languages in the preferences
- options menu of today's browsers). When an error document in
- the client's primary language version is unavailable, the
- secondary languages are tried or a default (fallback) version
- is used.</p>
-
- <p>You have full flexibility in designing your error documents
- to your personal taste (or your company's conventions). For
- demonstration purposes, we present a simple generic error
- document scheme. For this hypothetic server, we assume that all
- error messages...</p>
-
- <ul>
- <li>possibly are served by different virtual hosts (different
- host name, different IP address, or different port) on the
- server machine,</li>
-
- <li>show a predefined company logo in the right top of the
- message (selectable by virtual host),</li>
-
- <li>print the error title first, followed by an explanatory
- text and (depending on the error context) help on how to
- resolve the error,</li>
-
- <li>have some kind of standardized background image,</li>
-
- <li>display an apache logo and a feedback email address at
- the bottom of the error message.</li>
- </ul>
-
- <p>An example of a "document not found" message for a german
- client might look like this:</p>
-
- <p><img src="../images/custom_errordocs.gif"
- alt="[Needs graphics capability to display]" /></p>
-
- <p>All links in the document as well as links to the server's
- administrator mail address, and even the name and port of the
- serving virtual host are inserted in the error document at
- "run-time", i.e., when the error actually occurs.</p>
- </section>
-
- <section id="createdir">
-
- <title>Creating an ErrorDocument directory</title>
-
- <p>For this concept to work as easily as possible, we must take
- advantage of as much server support as we can get:</p>
-
- <ol>
- <li>By defining the MultiViews <directive
- module="core">Options</directive>, we
- enable the language selection of the most appropriate
- language alternative (content negotiation).</li>
-
- <li>By setting the <directive
- module="mod_negotiation">LanguagePriority</directive>
- directive we define a set of default fallback languages in
- the situation where the client's browser did not express any
- preference at all.</li>
-
- <li>By enabling <module>mod_include</module>
- (and disallowing execution of cgi scripts for
- security reasons), we allow the server to include building
- blocks of the error message, and to substitute the value of
- certain environment variables into the generated document
- (dynamic HTML) or even to conditionally include or omit parts
- of the text.</li>
-
- <li>The <directive
- module="mod_mime">AddHandler</directive> and <directive
- module="mod_mime">AddType</directive> directives
- are useful for automatically SSI-expanding all files with a
- <code>.shtml</code> suffix to <em>text/html</em>.</li>
-
- <li>By using the <directive
- module="mod_alias">Alias</directive> directive, we
- keep the error document directory outside of the document
- tree because it can be regarded more as a server part than
- part of the document tree.</li>
-
- <li>The <directive type="section"
- module="core">Directory</directive> block
- restricts these "special" settings to the error document
- directory and avoids an impact on any of the settings for the
- regular document tree.</li>
-
- <li>For each of the error codes to be handled (see RFC2068
- for an exact description of each error code, or look at
- <code>src/main/http_protocol.c</code> if you wish to see
- apache's standard messages), an <directive
- module="core">ErrorDocument</directive> in
- the aliased <code>/errordocs</code> directory is defined.
- Note that we only define the basename of the document here
- because the MultiViews option will select the best candidate
- based on the language suffixes and the client's preferences.
- Any error situation with an error code <em>not</em> handled
- by a custom document will be dealt with by the server in the
- standard way (<em>i.e.</em>, a plain error message in
- english).</li>
-
- <li>Finally, the <directive
- module="core">AllowOverride</directive> directive tells
- apache that it is not necessary to look for a .htaccess file
- in the /errordocs directory: a minor speed optimization.</li>
- </ol>
-
- <p>The resulting <code>httpd.conf</code> configuration would then
- look similar to this:</p>
-
- <note><title>Note</title>Note that you can define your own
- error messages using this method for only part of the document
- tree, e.g., a /~user/ subtree. In this case, the configuration
- could as well be put into the .htaccess file at the root of the
- subtree, and the <Directory> and </Directory>
- directives -but not the contained directives- must be
- omitted.</note>
-
- <example>
- LanguagePriority en fr de <br />
- Alias /errordocs /usr/local/apache/errordocs <br />
- <br />
- <Directory /usr/local/apache/errordocs> <br />
- <indent>
- AllowOverride none <br />
- Options MultiViews IncludesNoExec FollowSymLinks <br />
- AddType text/html .shtml <br />
- <FilesMatch "\.shtml[.$]"> <br />
- <indent>
- SetOutputFilter INCLUDES <br />
- </indent>
- </FilesMatch> <br />
- </indent>
- </Directory> <br />
- <br />
- # "400 Bad Request", <br />
- ErrorDocument 400 /errordocs/400 <br />
- # "401 Authorization Required", <br />
- ErrorDocument 401 /errordocs/401 <br />
- # "403 Forbidden", <br />
- ErrorDocument 403 /errordocs/403 <br />
- # "404 Not Found", <br />
- ErrorDocument 404 /errordocs/404 <br />
- # "500 Internal Server Error", <br />
- ErrorDocument 500 /errordocs/500 <br />
- </example>
-
- <p>The directory for the error messages (here:
- <code>/usr/local/apache/errordocs/</code>) must then be created
- with the appropriate permissions (readable and executable by
- the server uid or gid, only writable for the administrator).</p>
-
- <section id="naming">
-
- <title>Naming the Individual Error Document files</title>
-
- <p>By defining the <code>MultiViews</code> option, the server was
- told to automatically scan the directory for matching variants
- (looking at language and content type suffixes) when a
- requested document was not found. In the configuration, we
- defined the names for the error documents to be just their
- error number (without any suffix).</p>
-
- <p>The names of the individual error documents are now
- determined like this (I'm using 403 as an example, think of it
- as a placeholder for any of the configured error
- documents):</p>
-
- <ul>
- <li>No file errordocs/403 should exist. Otherwise, it would
- be found and served (with the DefaultType, usually
- text/plain), all negotiation would be bypassed.</li>
-
- <li>For each language for which we have an internationalized
- version (note that this need not be the same set of languages
- for each error code - you can get by with a single language
- version until you actually <em>have</em> translated
- versions), a document
- <code>errordocs/403.shtml.<em>lang</em></code> is created and
- filled with the error text in that language (<a
- href="#createdocs">see below</a>).</li>
-
- <li>One fallback document called
- <code>errordocs/403.shtml</code> is created, usually by
- creating a symlink to the default language variant (<a
- href="#fallback">see below</a>).</li>
- </ul>
- </section>
-
- <section id="headfoot">
-
- <title>The Common Header and Footer Files</title>
-
- <p>By putting as much layout information in two special "include
- files", the error documents can be reduced to a bare minimum.</p>
-
- <p>One of these layout files defines the HTML document header
- and a configurable list of paths to the icons to be shown in
- the resulting error document. These paths are exported as a set
- of SSI environment variables and are later evaluated by the
- "footer" special file. The title of the current error (which is
- put into the TITLE tag and an H1 header) is simply passed in
- from the main error document in a variable called
- <code>title</code>.</p>
-
- <p><strong>By changing this file, the layout of all generated
- error messages can be changed in a second.</strong> (By
- exploiting the features of SSI, you can easily define
- different layouts based on the current virtual host, or even
- based on the client's domain name).</p>
-
- <p>The second layout file describes the footer to be displayed
- at the bottom of every error message. In this example, it shows
- an apache logo, the current server time, the server version
- string and adds a mail reference to the site's webmaster.</p>
-
- <p>For simplicity, the header file is simply called
- <code>head.shtml</code> because it contains server-parsed
- content but no language specific information. The footer file
- exists once for each language translation, plus a symlink for
- the default language.</p>
-
- <example>
- for English, French and German versions (default english) <br />
- <br />
- foot.shtml.en, <br />
- foot.shtml.fr, <br />
- foot.shtml.de, <br />
- foot.shtml symlink to <br />
- foot.shtml.en
- </example>
-
- <p>Both files are included into the error document by using the
- directives <code><!--#include virtual="head" --></code>
- and <code><!--#include virtual="foot" --></code>
- respectively: the rest of the magic occurs in mod_negotiation
- and in mod_include.</p>
-
- <p>See <a href="#listings">the listings below</a> to see an
- actual HTML implementation of the discussed example.</p>
- </section>
-
- <section id="createdocs">
-
- <title>Creating ErrorDocuments in Different Languages</title>
-
- <p>After all this preparation work, little remains to be said
- about the actual documents. They all share a simple common
- structure:</p>
-
- <example>
- <!--#set var="title" value="<em>error description title</em>" --> <br />
- <!--#include virtual="head" --> <br />
- <indent>
- <em>explanatory error text</em> <br />
- </indent>
- <!--#include virtual="foot" -->
- </example>
-
- <p>In the <a href="#listings">listings section</a>, you can see an
- example of a [400 Bad Request] error document. Documents as
- simple as that certainly cause no problems to translate or
- expand.</p>
- </section>
-
- <section id="fallback">
-
- <title>The Fallback Language</title>
-
- <p>Do we need a special handling for languages other than those we
- have translations for? We did set the LanguagePriority, didn't
- we?!</p>
-
- <p>Well, the LanguagePriority directive is for the case where
- the client does not express any language priority at all. But
- what happens in the situation where the client wants one of the
- languages we do not have, and none of those we do have?</p>
-
- <p>Without doing anything, the Apache server will usually
- return a [406 no acceptable variant] error, listing the choices
- from which the client may select. But we're in an error message
- already, and important error information might get lost when
- the client had to choose a language representation first.</p>
-
- <p>So, in this situation it appears to be easier to define a
- fallback language (by copying or linking, <em>e.g.</em>, the
- english version to a language-less version). Because the
- negotiation algorithm prefers "more specialized" variants over
- "more generic" variants, these generic alternatives will only
- be chosen when the normal negotiation did not succeed.</p>
-
- <p>A simple shell script to do it (execute within the
- errordocs/ dir):</p>
-
- <example>
- for f in *.shtml.en <br />
- do <br />
- <indent>
- ln -s $f `basename $f .en` <br />
- </indent>
- done
- </example>
-
- </section>
- </section>
-
- <section id="proxy">
-
- <title>Customizing Proxy Error Messages</title>
-
- <p>As of Apache-1.3, it is possible to use the
- <code>ErrorDocument</code> mechanism for proxy error messages
- as well (previous versions always returned fixed predefined
- error messages).</p>
-
- <p>Most proxy errors return an error code of [500 Internal
- Server Error]. To find out whether a particular error document
- was invoked on behalf of a proxy error or because of some other
- server error, and what the reason for the failure was, you can
- check the contents of the new <code>ERROR_NOTES</code> CGI
- environment variable: if invoked for a proxy error, this
- variable will contain the actual proxy error message text in
- HTML form.</p>
-
- <p>The following excerpt demonstrates how to exploit the
- <code>ERROR_NOTES</code> variable within an error document:</p>
-
- <example>
- <!--#if expr="$REDIRECT_ERROR_NOTES = ''" --> <br />
- <br />
- <p> <br />
- <indent>
- The server encountered an unexpected condition <br />
- which prevented it from fulfilling the request. <br />
- </indent>
- </p> <br />
- <br />
- <p> <br />
- <indent>
- <a href="mailto:<!--#echo var="SERVER_ADMIN" -->" <br />
- SUBJECT="Error message [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> for <!--#echo var="REQUEST_URI" -->"> <br />
- Please forward this error screen to <!--#echo var="SERVER_NAME" -->'s <br />
- WebMaster</a>; it includes useful debugging information about <br />
- the Request which caused the error. <br />
- <br />
- <pre><!--#printenv --></pre> <br />
- </indent>
- </p> <br/>
- <br />
- <!--#else --> <br />
- <indent>
- <!--#echo var="REDIRECT_ERROR_NOTES" --><br />
- </indent>
- <br />
- <!--#endif -->
- </example>
-
- </section>
-
- <section id="listings">
-
- <title>HTML Listing of the Discussed Example</title>
-
- <p>So, to summarize our example, here's the complete listing of
- the <code>400.shtml.en</code> document. You will notice that it
- contains almost nothing but the error text (with conditional
- additions). Starting with this example, you will find it easy
- to add more error documents, or to translate the error
- documents to different languages.</p>
-
- <example>
- <!--#set var="title" value="Bad Request"--> <br />
- <!--#include virtual="head" --><br />
- <br />
- <p> <br />
- <indent>
- Your browser sent a request that this server could not understand: <br />
- <blockquote> <br />
- <indent>
- <strong><!--#echo var="REQUEST_URI" --></strong><br />
- </indent>
- </blockquote> <br />
- <br />
- The request could not be understood by the server due to malformed <br />
- syntax. The client should not repeat the request without <br />
- modifications. <br />
- </indent>
- </p> <br />
- <br />
- <p> <br />
- <indent>
- <!--#if expr="$HTTP_REFERER != ''" --> <br />
- <indent>
- Please inform the owner of <br />
- <a href="<!--#echo var="HTTP_REFERER" -->">the referring page</a> about <br />
- the malformed link. <br />
- </indent>
- <br />
- <!--#else --> <br />
- <indent>
- Please check your request for typing errors and retry. <br />
- </indent>
- <br />
- <!--#endif --> <br />
- </indent>
- </p> <br />
- <br />
- <!--#include virtual="foot" -->
- </example>
-
- <p>Here is the complete <code>head.shtml.en</code> file (the funny
- line breaks avoid empty lines in the document after SSI
- processing). Note the configuration section at top. That's
- where you configure the images and logos as well as the apache
- documentation directory. Look how this file displays two
- different logos depending on the content of the virtual host
- name ($SERVER_NAME), and that an animated apache logo is shown
- if the browser appears to support it (the latter requires
- server configuration lines of the form </p>
-
- <example>BrowserMatch "^Mozilla/[2-4]" anigif</example>
-
- <p>for browser types which support animated GIFs).</p>
-
- <example>
- <!--#if expr="$SERVER_NAME = /.*\.mycompany\.com/" --><br />
- <indent>
- <!--#set var="IMG_CorpLogo" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/CorpLogo.gif" --><br />
- <!--#set var="ALT_CorpLogo" value="Powered by Linux!" --><br />
- </indent>
- <br />
- <!--#else --> <br />
- <indent>
- <!--#set var="IMG_CorpLogo" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/PrivLogo.gif" --> <br />
- <!--#set var="ALT_CorpLogo" value="Powered by Linux!" --> <br />
- </indent>
- <!--#endif--> <br />
- <br />
- <!--#set var="IMG_BgImage" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/BgImage.gif" --> <br />
- <!--#set var="DOC_Apache" value="http://$SERVER_NAME:$SERVER_PORT/Apache/" --> <br />
- <br />
- <!--#if expr="$anigif" --> <br />
- <indent>
- <!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_anim.gif" --> <br />
- </indent>
- <!--#else--><br />
- <indent>
- <!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_pb.gif" --><br />
- </indent>
- <!--#endif--><br />
- <br />
-
- <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <br />
- <html> <br />
- <head> <br />
- <indent>
- <title> <br />
- [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> <br />
- </title> <br />
- </indent>
- </head> <br />
- <br />
- <body bgcolor="white" background="<!--#echo var="IMG_BgImage" -->"> <br />
- <indent>
- <h1 align="center"> <br />
- [<!--#echo var="REDIRECT_STATUS" -->]
- <!--#echo var="title" --> <br />
- <img src="<!--#echo var="IMG_CorpLogo" -->" <br />
- alt="<!--#echo var="ALT_CorpLogo" -->" align="right"> <br />
- </h1> <br />
- <br />
- <hr />
- <!-- ======================================================== --> <br />
- <div>
- </indent>
- </example>
-
- <p>and this is the <code>foot.shtml.en</code> file:</p>
-
- <example>
- <indent>
- </div> <br />
- <hr /> <br />
- <br />
- <div align="right"> <br />
- <indent>
- <small>Local Server time:
- <!--#echo var="DATE_LOCAL" --></small> <br />
- </indent>
- </div> <br />
- <br />
- <div align="center"><br />
- <indent>
- <a href="<!--#echo var="DOC_Apache" -->"> <br />
- <img src="<!--#echo var="IMG_Apache" -->" border="0" align="bottom" <br />
- alt="Powered by <!--#echo var="SERVER_SOFTWARE" -->"></a> <br />
- <br /><br />
-
- <small><!--#set var="var" value="Powered by $SERVER_SOFTWARE -- <br />
- File last modified on $LAST_MODIFIED" --> <br />
- <!--#echo var="var" --></small> <br />
- </indent>
- </div> <br />
- <br />
- <p>If the indicated error looks like a misconfiguration, please inform <br />
- <a href="mailto:<!--#echo var="SERVER_ADMIN" -->" <br />
- subject="Feedback about Error message [<!--#echo var="REDIRECT_STATUS" -->] <br />
- <!--#echo var="title" -->, req=<!--#echo var="REQUEST_URI" -->"> <br />
- <!--#echo var="SERVER_NAME" -->'s WebMaster</a>.<br />
- </p><br />
- </indent>
- <br />
- </body><br />
- </html>
- </example>
-
- <p>If you have tips to contribute, send mail to <a
- href="mailto:martin@apache.org">martin@apache.org</a></p>
- </section>
-
- </manualpage>
-